<script setup lang="ts">
import { onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app';
import { ref, reactive, toRefs, nextTick, onMounted } from 'vue'

type argument = {
    customListType?: 'default' | 'custom' | 'scroll'
    isPerformSearch?: boolean
    isPullDownRefresh?: boolean
    onFormSearch: (formData: any, onSuccess: Function) => void
    onRender?: Function
    options?: { [n: string]: string | number | boolean }
    emptyText?: string
    emptyHeight?: number
}

const props = withDefaults(defineProps<argument>(), {
    customListType: 'default',
    isPerformSearch: true,
    isPullDownRefresh: true,
    onFormSearch: () => {
        console.log('onFormSearch')
    },
    onRender: () => {
        console.log('onRender')
    },
    options: () => {
        return {}
    },
    emptyText: '暂无数据~',
    emptyHeight: 60
})

let { options, isPerformSearch, isPullDownRefresh, onFormSearch, onRender } = toRefs(props)

const list = ref<any[]>([])
const status = ref('loading')
const initing = ref(true)
const loading = ref(true)
const query = reactive({
    page: 1,
    limit: 10,
    total: 0
})

const loadData = (callback?: Function) => {
    uni.showLoading({ title: '数据加载中' })
    loading.value = true
    const params = { ...query, ...options.value } as { [n: string]: string | number | boolean }
    delete params.total

    setTimeout(() => {
        onFormSearch.value(params, ({ data }: { data: { data: any; total: number } }) => {
            loading.value = false
            initing.value = false
            callback && callback()
            query.page = params.page as number
            query.limit = params.limit as number
            query.total = data.total || 0
            list.value = [...list.value, ...data.data]

            status.value = query.page * query.limit >= query.total ? 'nomore' : 'loading'

            onRender.value && onRender.value(data)

            uni.hideLoading()
        })
    }, 100)
}

const refreshFn = (callback?: Function) => {
    query.page = 1
    query.total = 0
    list.value = []
    initing.value = true
    loadData(callback)
}

const onScrolltolower = () => {
    if (query.page * query.limit >= query.total) {
        status.value = 'nomore'
    } else {
        if (loading.value) return

        setTimeout(() => {
            status.value = 'loading'
            query.page += 1
            loadData()
        }, 1000)
    }
}

onMounted(() => {
    if (isPerformSearch.value) {
        nextTick(() => {
            refreshFn()
        })
    }
})

onPullDownRefresh(() => {
    if (isPullDownRefresh.value) refreshFn(() => uni.stopPullDownRefresh())
})

onReachBottom(() => {
    if (props.customListType !== 'scroll') {
        onScrolltolower()
    }
})

defineExpose({
    list,
    refreshFn
})
</script>

<template>
    <view v-if="!initing">
        <block v-if="list.length > 0">
            <template v-if="customListType === 'custom'">
                <slot v-bind:data="list" />
                <u-loadmore :status="status" />
            </template>
            <template v-else-if="customListType === 'scroll'">
                <scroll-view class="scroll-view" scroll-y @scrolltolower="onScrolltolower">
                    <view v-for="(item, index) in list" :key="index">
                        <slot v-bind:row="item" v-bind:index="index" />
                    </view>
                    <u-loadmore :status="status" />
                </scroll-view>
            </template>
            <template v-else>
                <view v-for="(item, index) in list" :key="index">
                    <slot v-bind:row="item" v-bind:index="index" />
                </view>
                <u-loadmore :status="status" />
            </template>
        </block>
        <ex-empty v-show="list.length <= 0 && status === 'nomore'" :height="emptyHeight" :tips="emptyText" />
    </view>
</template>

<style lang="scss" scoped>
.scroll-view {
    width: 100%;
    height: 100%;
}
</style>
